﻿#include "StdAfx.h"

namespace DuiLib {
    class CActiveXCtrl;

    class CActiveXWnd : public CWindowWnd {
      public:
        CActiveXWnd() : m_iLayeredTick(0), m_bDrawCaret(false) {}
        HWND Init(CActiveXCtrl *pOwner, HWND hWndParent);

        LPCTSTR GetWindowClassName() const;
        void OnFinalMessage(HWND hWnd);

        LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam);

      protected:
        void DoVerb(LONG iVerb);

        LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
        LRESULT OnTimer(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
        LRESULT OnMouseActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
        LRESULT OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
        LRESULT OnKillFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
        LRESULT OnEraseBkgnd(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
        LRESULT OnPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
        LRESULT OnPrint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);

      protected:
        enum {
            DEFAULT_TIMERID = 20,
        };

        CActiveXCtrl *m_pOwner;
        int m_iLayeredTick;
        bool m_bDrawCaret;
    };

    class CActiveXEnum : public IEnumUnknown {
      public:
        CActiveXEnum(IUnknown *pUnk) : m_pUnk(pUnk), m_dwRef(1), m_iPos(0) {
            m_pUnk->AddRef();
        }
        ~CActiveXEnum() {
            m_pUnk->Release();
        }

        LONG m_iPos;
        ULONG m_dwRef;
        IUnknown *m_pUnk;

        STDMETHOD_(ULONG, AddRef)() {
            return ++m_dwRef;
        }
        STDMETHOD_(ULONG, Release)() {
            LONG lRef = --m_dwRef;

            if( lRef == 0 ) delete this;

            return lRef;
        }
        STDMETHOD(QueryInterface)(REFIID riid, LPVOID *ppvObject) {
            *ppvObject = NULL;

            if( riid == IID_IUnknown ) *ppvObject = static_cast<IEnumUnknown *>(this);
            else if( riid == IID_IEnumUnknown ) *ppvObject = static_cast<IEnumUnknown *>(this);

            if( *ppvObject != NULL ) AddRef();

            return *ppvObject == NULL ? E_NOINTERFACE : S_OK;
        }
        STDMETHOD(Next)(ULONG celt, IUnknown **rgelt, ULONG *pceltFetched) {
            if( pceltFetched != NULL ) *pceltFetched = 0;

            if( ++m_iPos > 1 ) return S_FALSE;

            *rgelt = m_pUnk;
            (*rgelt)->AddRef();

            if( pceltFetched != NULL ) *pceltFetched = 1;

            return S_OK;
        }
        STDMETHOD(Skip)(ULONG celt) {
            m_iPos += celt;
            return S_OK;
        }
        STDMETHOD(Reset)(void) {
            m_iPos = 0;
            return S_OK;
        }
        STDMETHOD(Clone)(IEnumUnknown **ppenum) {
            return E_NOTIMPL;
        }
    };

    class CActiveXFrameWnd : public IOleInPlaceFrame {
      public:
        CActiveXFrameWnd(CActiveXUI *pOwner) : m_dwRef(1), m_pOwner(pOwner), m_pActiveObject(NULL) {
        }
        ~CActiveXFrameWnd() {
            if( m_pActiveObject != NULL ) m_pActiveObject->Release();
        }

        ULONG m_dwRef;
        CActiveXUI *m_pOwner;
        IOleInPlaceActiveObject *m_pActiveObject;

        // IUnknown
        STDMETHOD_(ULONG, AddRef)() {
            return ++m_dwRef;
        }
        STDMETHOD_(ULONG, Release)() {
            ULONG lRef = --m_dwRef;

            if( lRef == 0 ) delete this;

            return lRef;
        }
        STDMETHOD(QueryInterface)(REFIID riid, LPVOID *ppvObject) {
            *ppvObject = NULL;

            if( riid == IID_IUnknown ) *ppvObject = static_cast<IOleInPlaceFrame *>(this);
            else if( riid == IID_IOleWindow ) *ppvObject = static_cast<IOleWindow *>(this);
            else if( riid == IID_IOleInPlaceFrame ) *ppvObject = static_cast<IOleInPlaceFrame *>(this);
            else if( riid == IID_IOleInPlaceUIWindow ) *ppvObject = static_cast<IOleInPlaceUIWindow *>(this);

            if( *ppvObject != NULL ) AddRef();

            return *ppvObject == NULL ? E_NOINTERFACE : S_OK;
        }
        // IOleInPlaceFrameWindow
        STDMETHOD(InsertMenus)(HMENU /*hmenuShared*/, LPOLEMENUGROUPWIDTHS /*lpMenuWidths*/) {
            return S_OK;
        }
        STDMETHOD(SetMenu)(HMENU /*hmenuShared*/, HOLEMENU /*holemenu*/, HWND /*hwndActiveObject*/) {
            return S_OK;
        }
        STDMETHOD(RemoveMenus)(HMENU /*hmenuShared*/) {
            return S_OK;
        }
        STDMETHOD(SetStatusText)(LPCOLESTR /*pszStatusText*/) {
            return S_OK;
        }
        STDMETHOD(EnableModeless)(BOOL /*fEnable*/) {
            return S_OK;
        }
        STDMETHOD(TranslateAccelerator)(LPMSG /*lpMsg*/, WORD /*wID*/) {
            return S_FALSE;
        }
        // IOleWindow
        STDMETHOD(GetWindow)(HWND *phwnd) {
            if( m_pOwner == NULL ) return E_UNEXPECTED;

            *phwnd = m_pOwner->GetManager()->GetPaintWindow();
            return S_OK;
        }
        STDMETHOD(ContextSensitiveHelp)(BOOL /*fEnterMode*/) {
            return S_OK;
        }
        // IOleInPlaceUIWindow
        STDMETHOD(GetBorder)(LPRECT /*lprectBorder*/) {
            return S_OK;
        }
        STDMETHOD(RequestBorderSpace)(LPCBORDERWIDTHS /*pborderwidths*/) {
            return INPLACE_E_NOTOOLSPACE;
        }
        STDMETHOD(SetBorderSpace)(LPCBORDERWIDTHS /*pborderwidths*/) {
            return S_OK;
        }
        STDMETHOD(SetActiveObject)(IOleInPlaceActiveObject *pActiveObject, LPCOLESTR /*pszObjName*/) {
            if( pActiveObject != NULL ) pActiveObject->AddRef();

            if( m_pActiveObject != NULL ) m_pActiveObject->Release();

            m_pActiveObject = pActiveObject;
            return S_OK;
        }
    };

    class CActiveXCtrl :
        public IOleClientSite,
        public IOleInPlaceSiteWindowless,
        public IOleControlSite,
        public IObjectWithSite,
        public IOleContainer {
        friend class CActiveXUI;
        friend class CActiveXWnd;
      public:
        CActiveXCtrl();
        ~CActiveXCtrl();

        // IUnknown
        STDMETHOD_(ULONG, AddRef)();
        STDMETHOD_(ULONG, Release)();
        STDMETHOD(QueryInterface)(REFIID riid, LPVOID *ppvObject);

        // IObjectWithSite
        STDMETHOD(SetSite)(IUnknown *pUnkSite);
        STDMETHOD(GetSite)(REFIID riid, LPVOID *ppvSite);

        // IOleClientSite
        STDMETHOD(SaveObject)(void);
        STDMETHOD(GetMoniker)(DWORD dwAssign, DWORD dwWhichMoniker, IMoniker **ppmk);
        STDMETHOD(GetContainer)(IOleContainer **ppContainer);
        STDMETHOD(ShowObject)(void);
        STDMETHOD(OnShowWindow)(BOOL fShow);
        STDMETHOD(RequestNewObjectLayout)(void);

        // IOleInPlaceSiteWindowless
        STDMETHOD(CanWindowlessActivate)(void);
        STDMETHOD(GetCapture)(void);
        STDMETHOD(SetCapture)(BOOL fCapture);
        STDMETHOD(GetFocus)(void);
        STDMETHOD(SetFocus)(BOOL fFocus);
        STDMETHOD(GetDC)(LPCRECT pRect, DWORD grfFlags, HDC *phDC);
        STDMETHOD(ReleaseDC)(HDC hDC);
        STDMETHOD(InvalidateRect)(LPCRECT pRect, BOOL fErase);
        STDMETHOD(InvalidateRgn)(HRGN hRGN, BOOL fErase);
        STDMETHOD(ScrollRect)(INT dx, INT dy, LPCRECT pRectScroll, LPCRECT pRectClip);
        STDMETHOD(AdjustRect)(LPRECT prc);
        STDMETHOD(OnDefWindowMessage)(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT *plResult);

        // IOleInPlaceSiteEx
        STDMETHOD(OnInPlaceActivateEx)(BOOL *pfNoRedraw, DWORD dwFlags);
        STDMETHOD(OnInPlaceDeactivateEx)(BOOL fNoRedraw);
        STDMETHOD(RequestUIActivate)(void);

        // IOleInPlaceSite
        STDMETHOD(CanInPlaceActivate)(void);
        STDMETHOD(OnInPlaceActivate)(void);
        STDMETHOD(OnUIActivate)(void);
        STDMETHOD(GetWindowContext)(IOleInPlaceFrame **ppFrame, IOleInPlaceUIWindow **ppDoc, LPRECT lprcPosRect, LPRECT lprcClipRect, LPOLEINPLACEFRAMEINFO lpFrameInfo);
        STDMETHOD(Scroll)(SIZE scrollExtant);
        STDMETHOD(OnUIDeactivate)(BOOL fUndoable);
        STDMETHOD(OnInPlaceDeactivate)(void);
        STDMETHOD(DiscardUndoState)( void);
        STDMETHOD(DeactivateAndUndo)( void);
        STDMETHOD(OnPosRectChange)(LPCRECT lprcPosRect);

        // IOleWindow
        STDMETHOD(GetWindow)(HWND *phwnd);
        STDMETHOD(ContextSensitiveHelp)(BOOL fEnterMode);

        // IOleControlSite
        STDMETHOD(OnControlInfoChanged)(void);
        STDMETHOD(LockInPlaceActive)(BOOL fLock);
        STDMETHOD(GetExtendedControl)(IDispatch **ppDisp);
        STDMETHOD(TransformCoords)(POINTL *pPtlHimetric, POINTF *pPtfContainer, DWORD dwFlags);
        STDMETHOD(TranslateAccelerator)(MSG *pMsg, DWORD grfModifiers);
        STDMETHOD(OnFocus)(BOOL fGotFocus);
        STDMETHOD(ShowPropertyFrame)(void);

        // IOleContainer
        STDMETHOD(EnumObjects)(DWORD grfFlags, IEnumUnknown **ppenum);
        STDMETHOD(LockContainer)(BOOL fLock);

        // IParseDisplayName
        STDMETHOD(ParseDisplayName)(IBindCtx *pbc, LPOLESTR pszDisplayName, ULONG *pchEaten, IMoniker **ppmkOut);

      protected:
        HRESULT CreateActiveXWnd();

      protected:
        LONG m_dwRef;
        CActiveXUI *m_pOwner;
        CActiveXWnd *m_pWindow;
        IUnknown *m_pUnkSite;
        IViewObject *m_pViewObject;
        IOleInPlaceObjectWindowless *m_pInPlaceObject;
        bool m_bLocked;
        bool m_bFocused;
        bool m_bCaptured;
        bool m_bUIActivated;
        bool m_bInPlaceActive;
        bool m_bWindowless;
    };

    CActiveXCtrl::CActiveXCtrl() :
        m_dwRef(1),
        m_pOwner(NULL),
        m_pWindow(NULL),
        m_pUnkSite(NULL),
        m_pViewObject(NULL),
        m_pInPlaceObject(NULL),
        m_bLocked(false),
        m_bFocused(false),
        m_bCaptured(false),
        m_bWindowless(true),
        m_bUIActivated(false),
        m_bInPlaceActive(false) {
    }

    CActiveXCtrl::~CActiveXCtrl() {
        if( m_pWindow != NULL ) {
            ::DestroyWindow(*m_pWindow);
            delete m_pWindow;
        }

        if( m_pUnkSite != NULL )
            m_pUnkSite->Release();

        if( m_pViewObject != NULL )
            m_pViewObject->Release();

        if( m_pInPlaceObject != NULL )
            m_pInPlaceObject->Release();
    }

    STDMETHODIMP CActiveXCtrl::QueryInterface(REFIID riid, LPVOID *ppvObject) {
        *ppvObject = NULL;

        if( riid == IID_IUnknown )                       *ppvObject = static_cast<IOleWindow *>(this);
        else if( riid == IID_IOleClientSite )            *ppvObject = static_cast<IOleClientSite *>(this);
        else if( riid == IID_IOleInPlaceSiteWindowless ) *ppvObject = static_cast<IOleInPlaceSiteWindowless *>(this);
        else if( riid == IID_IOleInPlaceSiteEx )         *ppvObject = static_cast<IOleInPlaceSiteEx *>(this);
        else if( riid == IID_IOleInPlaceSite )           *ppvObject = static_cast<IOleInPlaceSite *>(this);
        else if( riid == IID_IOleWindow )                *ppvObject = static_cast<IOleWindow *>(this);
        else if( riid == IID_IOleControlSite )           *ppvObject = static_cast<IOleControlSite *>(this);
        else if( riid == IID_IOleContainer )             *ppvObject = static_cast<IOleContainer *>(this);
        else if( riid == IID_IObjectWithSite )           *ppvObject = static_cast<IObjectWithSite *>(this);

        if( *ppvObject != NULL ) AddRef();

        return *ppvObject == NULL ? E_NOINTERFACE : S_OK;
    }

    STDMETHODIMP_(ULONG) CActiveXCtrl::AddRef() {
        return ++m_dwRef;
    }

    STDMETHODIMP_(ULONG) CActiveXCtrl::Release() {
        LONG lRef = --m_dwRef;

        if( lRef == 0 ) delete this;

        return lRef;
    }

    STDMETHODIMP CActiveXCtrl::SetSite(IUnknown *pUnkSite) {
        if( m_pUnkSite != NULL ) {
            m_pUnkSite->Release();
            m_pUnkSite = NULL;
        }

        if( pUnkSite != NULL ) {
            m_pUnkSite = pUnkSite;
            m_pUnkSite->AddRef();
        }

        return S_OK;
    }

    STDMETHODIMP CActiveXCtrl::GetSite(REFIID riid, LPVOID *ppvSite) {
        if( ppvSite == NULL ) return E_POINTER;

        *ppvSite = NULL;

        if( m_pUnkSite == NULL ) return E_FAIL;

        return m_pUnkSite->QueryInterface(riid, ppvSite);
    }

    STDMETHODIMP CActiveXCtrl::SaveObject(void) {
        return E_NOTIMPL;
    }

    STDMETHODIMP CActiveXCtrl::GetMoniker(DWORD dwAssign, DWORD dwWhichMoniker, IMoniker **ppmk) {
        if( ppmk != NULL ) *ppmk = NULL;

        return E_NOTIMPL;
    }

    STDMETHODIMP CActiveXCtrl::GetContainer(IOleContainer **ppContainer) {
        if( ppContainer == NULL ) return E_POINTER;

        *ppContainer = NULL;
        HRESULT Hr = E_NOTIMPL;

        if( m_pUnkSite != NULL ) Hr = m_pUnkSite->QueryInterface(IID_IOleContainer, (LPVOID *) ppContainer);

        if( FAILED(Hr) ) Hr = QueryInterface(IID_IOleContainer, (LPVOID *) ppContainer);

        return Hr;
    }

    STDMETHODIMP CActiveXCtrl::ShowObject(void) {
        if( m_pOwner == NULL ) return E_UNEXPECTED;

        HDC hDC = ::GetDC(m_pOwner->m_hwndHost);

        if( hDC == NULL ) return E_FAIL;

        if( m_pViewObject != NULL ) m_pViewObject->Draw(DVASPECT_CONTENT, -1, NULL, NULL, NULL, hDC, (RECTL *) &m_pOwner->m_rcItem, (RECTL *) &m_pOwner->m_rcItem, NULL, NULL);

        ::ReleaseDC(m_pOwner->m_hwndHost, hDC);
        return S_OK;
    }

    STDMETHODIMP CActiveXCtrl::OnShowWindow(BOOL fShow) {
        return E_NOTIMPL;
    }

    STDMETHODIMP CActiveXCtrl::RequestNewObjectLayout(void) {
        return E_NOTIMPL;
    }

    STDMETHODIMP CActiveXCtrl::CanWindowlessActivate(void) {
        return S_OK;  // Yes, we can!!
    }

    STDMETHODIMP CActiveXCtrl::GetCapture(void) {
        if( m_pOwner == NULL )
            return E_UNEXPECTED;

        return m_bCaptured ? S_OK : S_FALSE;
    }

    STDMETHODIMP CActiveXCtrl::SetCapture(BOOL fCapture) {
        if( m_pOwner == NULL ) return E_UNEXPECTED;

        m_bCaptured = (fCapture == TRUE);

        if( fCapture )
            ::SetCapture(m_pOwner->m_hwndHost);
        else
            ::ReleaseCapture();

        return S_OK;
    }

    STDMETHODIMP CActiveXCtrl::GetFocus(void) {
        if( m_pOwner == NULL ) return E_UNEXPECTED;

        return m_bFocused ? S_OK : S_FALSE;
    }

    STDMETHODIMP CActiveXCtrl::SetFocus(BOOL fFocus) {
        if( m_pOwner == NULL ) return E_UNEXPECTED;

        if( fFocus ) m_pOwner->SetFocus();

        m_bFocused = (fFocus == TRUE);
        return S_OK;
    }

    STDMETHODIMP CActiveXCtrl::GetDC(LPCRECT pRect, DWORD grfFlags, HDC *phDC) {
        if( phDC == NULL ) return E_POINTER;

        if( m_pOwner == NULL ) return E_UNEXPECTED;

        if( m_bWindowless ) return S_FALSE;

        *phDC = ::GetDC(m_pOwner->m_hwndHost);

        if( (grfFlags & OLEDC_PAINTBKGND) != 0 ) {
            CDuiRect rcItem = m_pOwner->GetPos();

            if( !m_bWindowless ) rcItem.ResetOffset();

            ::FillRect(*phDC, &rcItem, (HBRUSH) (COLOR_WINDOW + 1));
        }

        return S_OK;
    }

    STDMETHODIMP CActiveXCtrl::ReleaseDC(HDC hDC) {
        if( m_pOwner == NULL ) return E_UNEXPECTED;

        ::ReleaseDC(m_pOwner->m_hwndHost, hDC);
        return S_OK;
    }

    STDMETHODIMP CActiveXCtrl::InvalidateRect(LPCRECT pRect, BOOL fErase) {
        if( m_pOwner == NULL ) return E_UNEXPECTED;

        if( m_pOwner->m_hwndHost == NULL ) return E_FAIL;

        return ::InvalidateRect(m_pOwner->m_hwndHost, pRect, fErase) ? S_OK : E_FAIL;
    }

    STDMETHODIMP CActiveXCtrl::InvalidateRgn(HRGN hRGN, BOOL fErase) {
        if( m_pOwner == NULL ) return E_UNEXPECTED;

        return ::InvalidateRgn(m_pOwner->m_hwndHost, hRGN, fErase) ? S_OK : E_FAIL;
    }

    STDMETHODIMP CActiveXCtrl::ScrollRect(INT dx, INT dy, LPCRECT pRectScroll, LPCRECT pRectClip) {
        return S_OK;
    }

    STDMETHODIMP CActiveXCtrl::AdjustRect(LPRECT prc) {
        return S_OK;
    }

    STDMETHODIMP CActiveXCtrl::OnDefWindowMessage(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT *plResult) {
        if( m_pOwner == NULL ) return E_UNEXPECTED;

        *plResult = ::DefWindowProc(m_pOwner->m_hwndHost, msg, wParam, lParam);
        return S_OK;
    }

    STDMETHODIMP CActiveXCtrl::OnInPlaceActivateEx(BOOL *pfNoRedraw, DWORD dwFlags) {
        ASSERT(m_pInPlaceObject == NULL);

        if( m_pOwner == NULL ) return E_UNEXPECTED;

        if( m_pOwner->m_pUnk == NULL ) return E_UNEXPECTED;

        ::OleLockRunning(m_pOwner->m_pUnk, TRUE, FALSE);
        HWND hWndFrame = m_pOwner->GetManager()->GetPaintWindow();
        HRESULT Hr = E_FAIL;

        if( (dwFlags & ACTIVATE_WINDOWLESS) != 0 ) {
            m_bWindowless = true;
            Hr = m_pOwner->m_pUnk->QueryInterface(IID_IOleInPlaceObjectWindowless, (LPVOID *) &m_pInPlaceObject);
            m_pOwner->m_hwndHost = hWndFrame;
            m_pOwner->GetManager()->AddMessageFilter(m_pOwner);
        }

        if( FAILED(Hr) ) {
            m_bWindowless = false;
            Hr = CreateActiveXWnd();

            if( FAILED(Hr) ) return Hr;

            Hr = m_pOwner->m_pUnk->QueryInterface(IID_IOleInPlaceObject, (LPVOID *) &m_pInPlaceObject);
        }

        if( m_pInPlaceObject != NULL && !m_pOwner->IsMFC() ) {
            CDuiRect rcItem = m_pOwner->m_rcItem;

            if( !m_bWindowless ) rcItem.ResetOffset();

            m_pInPlaceObject->SetObjectRects(&rcItem, &rcItem);
        }

        m_bInPlaceActive = SUCCEEDED(Hr);
        return Hr;
    }

    STDMETHODIMP CActiveXCtrl::OnInPlaceDeactivateEx(BOOL fNoRedraw) {
        m_bInPlaceActive = false;

        if( m_pInPlaceObject != NULL ) {
            m_pInPlaceObject->Release();
            m_pInPlaceObject = NULL;
        }

        if( m_pWindow != NULL ) {
            ::DestroyWindow(*m_pWindow);
            delete m_pWindow;
            m_pWindow = NULL;
        }

        return S_OK;
    }

    STDMETHODIMP CActiveXCtrl::RequestUIActivate(void) {
        return S_OK;
    }

    STDMETHODIMP CActiveXCtrl::CanInPlaceActivate(void) {
        return S_OK;
    }

    STDMETHODIMP CActiveXCtrl::OnInPlaceActivate(void) {
        BOOL bDummy = FALSE;
        return OnInPlaceActivateEx(&bDummy, 0);
    }

    STDMETHODIMP CActiveXCtrl::OnUIActivate(void) {
        m_bUIActivated = true;
        return S_OK;
    }

    STDMETHODIMP CActiveXCtrl::GetWindowContext(IOleInPlaceFrame **ppFrame, IOleInPlaceUIWindow **ppDoc, LPRECT lprcPosRect, LPRECT lprcClipRect, LPOLEINPLACEFRAMEINFO lpFrameInfo) {
        if( ppDoc == NULL ) return E_POINTER;

        if( ppFrame == NULL ) return E_POINTER;

        if( lprcPosRect == NULL ) return E_POINTER;

        if( lprcClipRect == NULL ) return E_POINTER;

        if (m_pWindow) {
            ::GetClientRect(m_pWindow->GetHWND(), lprcPosRect);
            ::GetClientRect(m_pWindow->GetHWND(), lprcClipRect);
        }

        *ppFrame = new CActiveXFrameWnd(m_pOwner);
        *ppDoc = NULL;
        ACCEL ac = { 0 };
        HACCEL hac = ::CreateAcceleratorTable(&ac, 1);
        lpFrameInfo->cb = sizeof(OLEINPLACEFRAMEINFO);
        lpFrameInfo->fMDIApp = FALSE;
        lpFrameInfo->hwndFrame = m_pOwner->GetManager()->GetPaintWindow();
        lpFrameInfo->haccel = hac;
        lpFrameInfo->cAccelEntries = 1;
        return S_OK;
    }

    STDMETHODIMP CActiveXCtrl::Scroll(SIZE scrollExtant) {
        return E_NOTIMPL;
    }

    STDMETHODIMP CActiveXCtrl::OnUIDeactivate(BOOL fUndoable) {
        m_bUIActivated = false;
        return S_OK;
    }

    STDMETHODIMP CActiveXCtrl::OnInPlaceDeactivate(void) {
        return OnInPlaceDeactivateEx(TRUE);
    }

    STDMETHODIMP CActiveXCtrl::DiscardUndoState(void) {
        return E_NOTIMPL;
    }

    STDMETHODIMP CActiveXCtrl::DeactivateAndUndo(void) {
        return E_NOTIMPL;
    }

    STDMETHODIMP CActiveXCtrl::OnPosRectChange(LPCRECT lprcPosRect) {
        return E_NOTIMPL;
    }

    STDMETHODIMP CActiveXCtrl::GetWindow(HWND *phwnd) {
        if( m_pOwner == NULL )
            return E_UNEXPECTED;

        if( m_pOwner->m_hwndHost == NULL )
            CreateActiveXWnd();

        if( m_pOwner->m_hwndHost == NULL )
            return E_FAIL;

        *phwnd = m_pOwner->m_hwndHost;
        return S_OK;
    }

    STDMETHODIMP CActiveXCtrl::ContextSensitiveHelp(BOOL fEnterMode) {
        return S_OK;
    }

    STDMETHODIMP CActiveXCtrl::OnControlInfoChanged(void) {
        return S_OK;
    }

    STDMETHODIMP CActiveXCtrl::LockInPlaceActive(BOOL fLock) {
        return S_OK;
    }

    STDMETHODIMP CActiveXCtrl::GetExtendedControl(IDispatch **ppDisp) {
        if( ppDisp == NULL ) return E_POINTER;

        if( m_pOwner == NULL ) return E_UNEXPECTED;

        if( m_pOwner->m_pUnk == NULL ) return E_UNEXPECTED;

        return m_pOwner->m_pUnk->QueryInterface(IID_IDispatch, (LPVOID *) ppDisp);
    }

    STDMETHODIMP CActiveXCtrl::TransformCoords(POINTL *pPtlHimetric, POINTF *pPtfContainer, DWORD dwFlags) {
        return S_OK;
    }

    STDMETHODIMP CActiveXCtrl::TranslateAccelerator(MSG *pMsg, DWORD grfModifiers) {
        return S_FALSE;
    }

    STDMETHODIMP CActiveXCtrl::OnFocus(BOOL fGotFocus) {
        m_bFocused = (fGotFocus == TRUE);
        return S_OK;
    }

    STDMETHODIMP CActiveXCtrl::ShowPropertyFrame(void) {
        return E_NOTIMPL;
    }

    STDMETHODIMP CActiveXCtrl::EnumObjects(DWORD grfFlags, IEnumUnknown **ppenum) {
        if( ppenum == NULL ) return E_POINTER;

        if( m_pOwner == NULL ) return E_UNEXPECTED;

        *ppenum = new CActiveXEnum(m_pOwner->m_pUnk);
        return S_OK;
    }

    STDMETHODIMP CActiveXCtrl::LockContainer(BOOL fLock) {
        m_bLocked = fLock != FALSE;
        return S_OK;
    }

    STDMETHODIMP CActiveXCtrl::ParseDisplayName(IBindCtx *pbc, LPOLESTR pszDisplayName, ULONG *pchEaten, IMoniker **ppmkOut) {
        return E_NOTIMPL;
    }

    HRESULT CActiveXCtrl::CreateActiveXWnd() {
        if( m_pWindow != NULL )
            return S_OK;

        m_pWindow = new CActiveXWnd;

        if( m_pWindow == NULL )
            return E_OUTOFMEMORY;

        m_pOwner->m_hwndHost = m_pWindow->Init(this, m_pOwner->GetManager()->GetPaintWindow());
        return S_OK;
    }



    HWND CActiveXWnd::Init(CActiveXCtrl *pOwner, HWND hWndParent) {
        m_pOwner = pOwner;
        UINT uStyle = WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
        Create(hWndParent, _T("UIActiveX"), uStyle, 0L, 0, 0, 0, 0, NULL);
        return m_hWnd;
    }

    LPCTSTR CActiveXWnd::GetWindowClassName() const {
        return _T("ActiveXWnd");
    }

    void CActiveXWnd::OnFinalMessage(HWND hWnd) {
        if(m_pOwner && m_pOwner->m_pOwner && m_pOwner->m_pOwner->GetManager()->IsLayered() ) {
            m_pOwner->m_pOwner->GetManager()->RemoveNativeWindow(hWnd);
        }
    }

    void CActiveXWnd::DoVerb(LONG iVerb) {
        if( m_pOwner == NULL )
            return;

        if( m_pOwner->m_pOwner == NULL )
            return;

        IOleObject *pUnk = NULL;
        m_pOwner->m_pOwner->GetControl(IID_IOleObject, (LPVOID *) &pUnk);

        if( pUnk == NULL )
            return;

        CSafeRelease<IOleObject> RefOleObject = pUnk;
        IOleClientSite *pOleClientSite = NULL;
        m_pOwner->QueryInterface(IID_IOleClientSite, (LPVOID *) &pOleClientSite);
        CSafeRelease<IOleClientSite> RefOleClientSite = pOleClientSite;
        pUnk->DoVerb(iVerb, NULL, pOleClientSite, 0, m_hWnd, &m_pOwner->m_pOwner->GetPos());
    }

    LRESULT CActiveXWnd::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) {
        LRESULT lRes = 0;
        BOOL bHandled = TRUE;

        switch( uMsg ) {
            case WM_CREATE:
                lRes = OnCreate(uMsg, wParam, lParam, bHandled);
                break;

            case WM_TIMER:
                lRes = OnTimer(uMsg, wParam, lParam, bHandled);
                break;

            case WM_PAINT:
                lRes = OnPaint(uMsg, wParam, lParam, bHandled);
                break;

            case WM_PRINT:
                lRes = OnPrint(uMsg, wParam, lParam, bHandled);
                break;

            case WM_SETFOCUS:
                lRes = OnSetFocus(uMsg, wParam, lParam, bHandled);
                break;

            case WM_KILLFOCUS:
                lRes = OnKillFocus(uMsg, wParam, lParam, bHandled);
                break;

            case WM_ERASEBKGND:
                lRes = OnEraseBkgnd(uMsg, wParam, lParam, bHandled);
                break;

            case WM_MOUSEACTIVATE:
                lRes = OnMouseActivate(uMsg, wParam, lParam, bHandled);
                break;

            case WM_MOUSEWHEEL:
                break;

            default:
                bHandled = FALSE;
        }

        if( !bHandled )
            return CWindowWnd::HandleMessage(uMsg, wParam, lParam);

        return lRes;
    }

    LRESULT CActiveXWnd::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) {
        if( m_pOwner->m_pOwner->GetManager()->IsLayered() ) {
            ::SetTimer(m_hWnd, CARET_TIMERID, ::GetCaretBlinkTime(), NULL);
        }

        return 0;
    }

    LRESULT CActiveXWnd::OnTimer(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) {
        if (wParam == DEFAULT_TIMERID) {
            if (m_pOwner->m_pOwner->GetManager()->IsLayered()) {
                //m_pOwner->m_pOwner->GetManager()->AddNativeWindow(m_pOwner->m_pOwner, m_hWnd);
                m_iLayeredTick += 1;

                if (m_iLayeredTick >= 10) {
                    m_iLayeredTick = 0;
                    m_bDrawCaret = !m_bDrawCaret;
                }
            }

            return 0;
        }

        bHandled = FALSE;
        return 0;
    }

    LRESULT CActiveXWnd::OnEraseBkgnd(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) {
        if( m_pOwner->m_pViewObject == NULL )
            bHandled = FALSE;

        return 1;
    }

    LRESULT CActiveXWnd::OnMouseActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) {
        IOleObject *pUnk = NULL;
        m_pOwner->m_pOwner->GetControl(IID_IOleObject, (LPVOID *) &pUnk);

        if( pUnk == NULL ) return 0;

        CSafeRelease<IOleObject> RefOleObject = pUnk;
        DWORD dwMiscStatus = 0;
        pUnk->GetMiscStatus(DVASPECT_CONTENT, &dwMiscStatus);

        if( (dwMiscStatus & OLEMISC_NOUIACTIVATE) != 0 )
            return 0;

        if( !m_pOwner->m_bInPlaceActive )
            DoVerb(OLEIVERB_INPLACEACTIVATE);

        bHandled = FALSE;
        return 0;
    }

    LRESULT CActiveXWnd::OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) {
        bHandled = FALSE;
        m_pOwner->m_bFocused = true;

        if( !m_pOwner->m_bUIActivated )
            DoVerb(OLEIVERB_UIACTIVATE);

        return 0;
    }

    LRESULT CActiveXWnd::OnKillFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) {
        bHandled = FALSE;
        m_pOwner->m_bFocused = false;
        return 0;
    }

    LRESULT CActiveXWnd::OnPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) {
        PAINTSTRUCT ps = { 0 };
        ::BeginPaint(m_hWnd, &ps);
        ::EndPaint(m_hWnd, &ps);
        return 1;
    }

    LRESULT CActiveXWnd::OnPrint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) {
        RECT rcClient;
        ::GetClientRect(m_hWnd, &rcClient);
        m_pOwner->m_pViewObject->Draw(DVASPECT_CONTENT, -1, NULL, NULL, NULL, (HDC)wParam, (RECTL *) &rcClient, NULL, NULL, NULL);

        if (m_bDrawCaret ) {
            RECT rcPos = m_pOwner->m_pOwner->GetPos();
            GUITHREADINFO guiThreadInfo;
            guiThreadInfo.cbSize = sizeof(GUITHREADINFO);
            ::GetGUIThreadInfo(NULL, &guiThreadInfo);

            if (guiThreadInfo.hwndCaret) {
                POINT ptCaret;
                ptCaret.x = guiThreadInfo.rcCaret.left;
                ptCaret.y = guiThreadInfo.rcCaret.top;
                ::ClientToScreen(guiThreadInfo.hwndCaret, &ptCaret);
                ::ScreenToClient(m_pOwner->m_pOwner->GetManager()->GetPaintWindow(), &ptCaret);

                if( ::PtInRect(&rcPos, ptCaret) ) {
                    RECT rcCaret;
                    rcCaret = guiThreadInfo.rcCaret;
                    rcCaret.right = rcCaret.left;
                    CRenderEngine::DrawLine((HDC)wParam, rcCaret, 1, 0xFF000000);
                }
            }
        }

        return 1;
    }

    /////////////////////////////////////////////////////////////////////////////////////
    //
    //
    IMPLEMENT_DUICONTROL(CActiveXUI)

    CActiveXUI::CActiveXUI() :
        m_pUnk(NULL)
        , m_pControl(NULL)
        , m_hwndHost(NULL)
        , m_bCreated(false)
        , m_bDelayCreate(true)
        , m_bMFC(false) {
        m_clsid = IID_NULL;
    }

    CActiveXUI::~CActiveXUI() {
        ReleaseControl();
    }

    LPCTSTR CActiveXUI::GetClass() const {
        return DUI_CTR_ACTIVEX;
    }

    LPVOID CActiveXUI::GetInterface(LPCTSTR pstrName) {
        if( _tcscmp(pstrName, DUI_CTR_ACTIVEX) == 0 )
            return static_cast<CActiveXUI *>(this);

        return CControlUI::GetInterface(pstrName);
    }

    HWND CActiveXUI::GetHostWindow() const {
        return m_hwndHost;
    }

    static void PixelToHiMetric(const SIZEL *lpSizeInPix, LPSIZEL lpSizeInHiMetric) {
#define HIMETRIC_PER_INCH   2540
#define MAP_PIX_TO_LOGHIM(x,ppli)   MulDiv(HIMETRIC_PER_INCH, (x), (ppli))
#define MAP_LOGHIM_TO_PIX(x,ppli)   MulDiv((ppli), (x), HIMETRIC_PER_INCH)
        int nPixelsPerInchX;    // Pixels per logical inch along width
        int nPixelsPerInchY;    // Pixels per logical inch along height
        HDC hDCScreen = ::GetDC(NULL);
        nPixelsPerInchX = ::GetDeviceCaps(hDCScreen, LOGPIXELSX);
        nPixelsPerInchY = ::GetDeviceCaps(hDCScreen, LOGPIXELSY);
        ::ReleaseDC(NULL, hDCScreen);
        lpSizeInHiMetric->cx = MAP_PIX_TO_LOGHIM(lpSizeInPix->cx, nPixelsPerInchX);
        lpSizeInHiMetric->cy = MAP_PIX_TO_LOGHIM(lpSizeInPix->cy, nPixelsPerInchY);
    }

    void CActiveXUI::SetVisible(bool bVisible) {
        CControlUI::SetVisible(bVisible);

        if( m_hwndHost != NULL && !m_pControl->m_bWindowless )
            ::ShowWindow(m_hwndHost, IsVisible() ? SW_SHOW : SW_HIDE);
    }

    void CActiveXUI::SetInternVisible(bool bVisible) {
        CControlUI::SetInternVisible(bVisible);

        if( m_hwndHost != NULL && !m_pControl->m_bWindowless )
            ::ShowWindow(m_hwndHost, IsVisible() ? SW_SHOW : SW_HIDE);
    }

    void CActiveXUI::SetPos(RECT rc, bool bNeedInvalidate) {
        CControlUI::SetPos(rc, bNeedInvalidate);

        if( !m_bCreated )
            DoCreateControl();

        if( m_pUnk == NULL )
            return;

        if( m_pControl == NULL )
            return;

        SIZEL hmSize = { 0 };
        SIZEL pxSize = { 0 };
        pxSize.cx = m_rcItem.right - m_rcItem.left;
        pxSize.cy = m_rcItem.bottom - m_rcItem.top;
        PixelToHiMetric(&pxSize, &hmSize);

        if( m_pUnk != NULL ) {
            m_pUnk->SetExtent(DVASPECT_CONTENT, &hmSize);
        }

        if( m_pControl->m_pInPlaceObject != NULL ) {
            CDuiRect rcItem = m_rcItem;

            if( !m_pControl->m_bWindowless )
                rcItem.ResetOffset();

            m_pControl->m_pInPlaceObject->SetObjectRects(&rcItem, &rcItem);
        }

        if( !m_pControl->m_bWindowless ) {
            ASSERT(m_pControl->m_pWindow);
            ::MoveWindow(*m_pControl->m_pWindow, m_rcItem.left, m_rcItem.top, m_rcItem.right - m_rcItem.left, m_rcItem.bottom - m_rcItem.top, TRUE);
        }
    }

    void CActiveXUI::Move(SIZE szOffset, bool bNeedInvalidate) {
        CControlUI::Move(szOffset, bNeedInvalidate);

        if( !m_pControl->m_bWindowless ) {
            ASSERT(m_pControl->m_pWindow);
            ::MoveWindow(*m_pControl->m_pWindow, m_rcItem.left, m_rcItem.top, m_rcItem.right - m_rcItem.left, m_rcItem.bottom - m_rcItem.top, TRUE);
        }
    }

    bool CActiveXUI::DoPaint(HDC hDC, const RECT &rcPaint, CControlUI *pStopControl) {
        if( m_pControl != NULL && m_pControl->m_bWindowless && m_pControl->m_pViewObject != NULL ) {
            m_pControl->m_pViewObject->Draw(DVASPECT_CONTENT, -1, NULL, NULL, NULL, hDC, (RECTL *) &m_rcItem, (RECTL *) &m_rcItem, NULL, NULL);
        }

        return true;
    }

    void CActiveXUI::SetAttribute(LPCTSTR pstrName, LPCTSTR pstrValue) {
        if( _tcscmp(pstrName, _T("clsid")) == 0 )
            CreateControl(pstrValue);
        else if( _tcscmp(pstrName, _T("modulename")) == 0 )
            SetModuleName(pstrValue);
        else if( _tcscmp(pstrName, _T("delaycreate")) == 0 )
            SetDelayCreate(_tcscmp(pstrValue, _T("true")) == 0);
        else
            CControlUI::SetAttribute(pstrName, pstrValue);
    }

    LRESULT CActiveXUI::MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, bool &bHandled) {
        if( m_pControl == NULL )
            return 0;

        ASSERT(m_pControl->m_bWindowless);

        if( !m_pControl->m_bInPlaceActive )
            return 0;

        if( m_pControl->m_pInPlaceObject == NULL )
            return 0;

        if( !IsMouseEnabled() && uMsg >= WM_MOUSEFIRST && uMsg <= WM_MOUSELAST )
            return 0;

        if (!IsVisible())
            return 0;

        bool bWasHandled = true;

        if( (uMsg >= WM_MOUSEFIRST && uMsg <= WM_MOUSELAST) || uMsg == WM_SETCURSOR ) {
            // Mouse message only go when captured or inside rect
            DWORD dwHitResult = m_pControl->m_bCaptured ? HITRESULT_HIT : HITRESULT_OUTSIDE;

            if( dwHitResult == HITRESULT_OUTSIDE && m_pControl->m_pViewObject != NULL ) {
                IViewObjectEx *pViewEx = NULL;
                m_pControl->m_pViewObject->QueryInterface(IID_IViewObjectEx, (LPVOID *) &pViewEx);

                if( pViewEx != NULL ) {
                    POINT ptMouse = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
                    pViewEx->QueryHitPoint(DVASPECT_CONTENT, &m_rcItem, ptMouse, 0, &dwHitResult);
                    pViewEx->Release();
                }
            }

            if( dwHitResult != HITRESULT_HIT ) return 0;

            if( uMsg == WM_SETCURSOR ) bWasHandled = false;
        } else if( uMsg >= WM_KEYFIRST && uMsg <= WM_KEYLAST ) {
            // Keyboard messages just go when we have focus
            if( !IsFocused() ) return 0;
        } else {
            switch( uMsg ) {
                case WM_HELP:
                case WM_CONTEXTMENU:
                    bWasHandled = false;
                    break;

                default:
                    return 0;
            }
        }

        LRESULT lResult = 0;
        HRESULT Hr = m_pControl->m_pInPlaceObject->OnWindowMessage(uMsg, wParam, lParam, &lResult);

        if( Hr == S_OK )
            bHandled = bWasHandled;

        return lResult;
    }

    bool CActiveXUI::IsDelayCreate() const {
        return m_bDelayCreate;
    }

    void CActiveXUI::SetDelayCreate(bool bDelayCreate) {
        if( m_bDelayCreate == bDelayCreate ) return;

        if( bDelayCreate == false ) {
            if( m_bCreated == false && m_clsid != IID_NULL ) DoCreateControl();
        }

        m_bDelayCreate = bDelayCreate;
    }

    bool CActiveXUI::IsMFC() const {
        return m_bMFC;
    }

    void CActiveXUI::SetMFC(bool bMFC/* = false*/) {
        if( m_bMFC == bMFC ) return;

        m_bMFC = bMFC;
    }

    void CActiveXUI::OnShowActiveX() {
    }

    bool CActiveXUI::CreateControl(LPCTSTR pstrCLSID) {
        CLSID clsid = { 0 };
        OLECHAR szCLSID[100] = { 0 };
#ifndef _UNICODE
        ::MultiByteToWideChar(::GetACP(), 0, pstrCLSID, -1, szCLSID, lengthof(szCLSID) - 1);
#else
        _tcsncpy(szCLSID, pstrCLSID, lengthof(szCLSID) - 1);
#endif

        if( pstrCLSID[0] == '{' )
            ::CLSIDFromString(szCLSID, &clsid);
        else
            ::CLSIDFromProgID(szCLSID, &clsid);

        return CreateControl(clsid);
    }

    bool CActiveXUI::CreateControl(const CLSID clsid) {
        ASSERT(clsid != IID_NULL);

        if( clsid == IID_NULL )
            return false;

        m_bCreated = false;
        m_clsid = clsid;

        if( !m_bDelayCreate )
            DoCreateControl();

        return true;
    }

    void CActiveXUI::ReleaseControl() {
        // 移除消息链
        if(m_pManager != NULL) m_pManager->RemoveMessageFilter(this);

        if( m_pUnk != NULL ) {
            IObjectWithSite *pSite = NULL;
            m_pUnk->QueryInterface(IID_IObjectWithSite, (LPVOID *) &pSite);

            if( pSite != NULL ) {
                pSite->SetSite(NULL);
                pSite->Release();
            }

            if(!IsMFC()) {
                m_pUnk->Close(OLECLOSE_NOSAVE);
            }

            m_pUnk->SetClientSite(NULL);
            m_pUnk->Release();
            m_pUnk = NULL;
        }

        // 销毁CActiveXCtrl
        if( m_pControl != NULL ) {
            m_pControl->m_pOwner = NULL;
            m_pControl->Release();
            m_pControl = NULL;
        }

        m_hwndHost = NULL;
    }

    typedef HRESULT (__stdcall *DllGetClassObjectFunc)(REFCLSID rclsid, REFIID riid, LPVOID *ppv);

    bool CActiveXUI::DoCreateControl() {
        ReleaseControl();
        // At this point we'll create the ActiveX control
        m_bCreated = true;
        IOleControl *pOleControl = NULL;

        HRESULT hr = -1;

        if( !m_sModuleName.IsEmpty() ) {
            HMODULE hModule = ::LoadLibrary((LPCTSTR)m_sModuleName);

            if( hModule != NULL ) {
                IClassFactory *aClassFactory = NULL;
                DllGetClassObjectFunc aDllGetClassObjectFunc = (DllGetClassObjectFunc)::GetProcAddress(hModule, "DllGetClassObject");
                hr = aDllGetClassObjectFunc(m_clsid, IID_IClassFactory, (LPVOID *)&aClassFactory);

                if( SUCCEEDED(hr) ) {
                    hr = aClassFactory->CreateInstance(NULL, IID_IOleObject, (LPVOID *)&pOleControl);
                }

                aClassFactory->Release();
            }
        }

        if( FAILED(hr) ) {
            hr = ::CoCreateInstance(m_clsid, NULL, CLSCTX_ALL, IID_IOleControl, (LPVOID *)&pOleControl);
        }

        if (FAILED(hr)) {
            TraceMsgW(L"CActiveXUI CoCreateInstance failed, hr=%ld, GLE=%ld", hr, GetLastError());
            return false;
        }

        pOleControl->QueryInterface(IID_IOleObject, (LPVOID *) &m_pUnk);
        pOleControl->Release();

        if( m_pUnk == NULL )
            return false;

        // Create the host too
        m_pControl = new CActiveXCtrl();
        m_pControl->m_pOwner = this;
        // More control creation stuff
        DWORD dwMiscStatus = 0;
        m_pUnk->GetMiscStatus(DVASPECT_CONTENT, &dwMiscStatus);
        IOleClientSite *pOleClientSite = NULL;
        m_pControl->QueryInterface(IID_IOleClientSite, (LPVOID *) &pOleClientSite);
        CSafeRelease<IOleClientSite> RefOleClientSite = pOleClientSite;

        // Initialize control
        if( (dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST) != 0 )
            m_pUnk->SetClientSite(pOleClientSite);

        IPersistStreamInit *pPersistStreamInit = NULL;
        m_pUnk->QueryInterface(IID_IPersistStreamInit, (LPVOID *) &pPersistStreamInit);

        if( pPersistStreamInit != NULL ) {
            hr = pPersistStreamInit->InitNew();
            pPersistStreamInit->Release();
        }

        if( FAILED(hr) )
            return false;

        if( (dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST) == 0 )
            m_pUnk->SetClientSite(pOleClientSite);

        // Grab the view...
        hr = m_pUnk->QueryInterface(IID_IViewObjectEx, (LPVOID *) &m_pControl->m_pViewObject);

        if( FAILED(hr) )
            hr = m_pUnk->QueryInterface(IID_IViewObject2, (LPVOID *) &m_pControl->m_pViewObject);

        if( FAILED(hr) )
            hr = m_pUnk->QueryInterface(IID_IViewObject, (LPVOID *) &m_pControl->m_pViewObject);

        // Activate and done...
        m_pUnk->SetHostNames(OLESTR("UIActiveX"), NULL);

        //     if( m_pManager != NULL )
        //m_pManager->SendNotify((CControlUI *)this, DUI_MSGTYPE_SHOWACTIVEX, 0, 0, false);
        OnShowActiveX();

        if( (dwMiscStatus & OLEMISC_INVISIBLEATRUNTIME) == 0 ) {
            try {
                if(m_pManager != NULL)
                    hr = m_pUnk->DoVerb(OLEIVERB_INPLACEACTIVATE, NULL, pOleClientSite, 0, m_pManager->GetPaintWindow(), &m_rcItem);
            } catch (...) {
            }
        }

        IObjectWithSite *pSite = NULL;
        m_pUnk->QueryInterface(IID_IObjectWithSite, (LPVOID *) &pSite);

        if( pSite != NULL ) {
            pSite->SetSite(static_cast<IOleClientSite *>(m_pControl));
            pSite->Release();
        }

        return SUCCEEDED(hr);
    }

    HRESULT CActiveXUI::GetControl(const IID iid, LPVOID *ppRet) {
        ASSERT(ppRet != NULL);
        ASSERT(*ppRet == NULL);

        if( ppRet == NULL )
            return E_POINTER;

        if( m_pUnk == NULL )
            return E_PENDING;

        return m_pUnk->QueryInterface(iid, (LPVOID *) ppRet);
    }

    CLSID CActiveXUI::GetClisd() const {
        return m_clsid;
    }

    CDuiString CActiveXUI::GetModuleName() const {
        return m_sModuleName;
    }

    void CActiveXUI::SetModuleName(LPCTSTR pstrText) {
        m_sModuleName = pstrText;
    }

} // namespace DuiLib
